﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Benchmark.Core.Communication.Data.Interface;

namespace Benchmark.Core.Communication.Data.Stream_Manager
{
  public  class PipeStreamManager:IStreamManager,IDisposable 
    {


        private Stream ioStream;
        private UnicodeEncoding streamEncoding;


        public PipeStreamManager(Stream ioStream)
        {
            this.ioStream = ioStream;
            streamEncoding = new UnicodeEncoding();
        }
        public int WriteByte(byte[] datainBytes)
        {

            var nma = ioStream as NamedPipeServerStream;
            var nmc = ioStream as NamedPipeClientStream;
            int lengthofStream = datainBytes.Length;
            int lengthTransmitted = 0;
            int continueStream;
            int totalTransmittedLength = 0;
            if (nma != null)
            {

                while (totalTransmittedLength < datainBytes.Length)
               {
                   
                   if (lengthofStream > Byte.MaxValue)
                   {
                       lengthTransmitted = Byte.MaxValue;
                       continueStream = 1;
                   }
                   else
                   {
                       lengthTransmitted = lengthofStream;
                       continueStream = 0;
                   }

                   nma.WriteByte((byte)lengthTransmitted);
                   nma.WriteByte((byte)continueStream);
                   nma.Write(datainBytes, 0, lengthTransmitted);
                   totalTransmittedLength = totalTransmittedLength + lengthTransmitted;
                   nma.WaitForPipeDrain();
                   lengthofStream = lengthofStream - lengthTransmitted;
               }
                        

              
                
               
            }

            else
            {

                while (totalTransmittedLength < datainBytes.Length)
                {

                    if (lengthofStream > Byte.MaxValue)
                    {
                        lengthTransmitted = Byte.MaxValue;
                        continueStream = 1;
                    }
                    else
                    {
                        lengthTransmitted = lengthofStream;
                        continueStream = 0;
                    }

                    nmc.WriteByte((byte)lengthTransmitted);
                    nmc.WriteByte((byte)continueStream);
                    nmc.Write(datainBytes, totalTransmittedLength, lengthTransmitted);
                    totalTransmittedLength = totalTransmittedLength + lengthTransmitted;
                    nmc.WaitForPipeDrain();
                    lengthofStream = lengthofStream - lengthTransmitted;
                }
                      
            }

            return (datainBytes.Length);
            
        }

        public byte[] ReadByte()
        {

            byte[] _bytesRead ;
            var nma = ioStream as NamedPipeServerStream;
            var nmc = ioStream as NamedPipeClientStream;
            List<Byte[]> StreamedData = new List<byte[]>();
             int length=0;
              int continueStream =1;
              if (nma != null)
              {


                  while (continueStream != 0)
                  {
                      length = nma.ReadByte();
                      continueStream = nma.ReadByte();
                   
                      _bytesRead = new byte[length];
                      nma.Read(_bytesRead, 0, length);
                      StreamedData.Add(_bytesRead);
                  }


              }

              else
              {

                  while (continueStream != 0)
                  {
                      length = nmc.ReadByte();
                
                      continueStream = nmc.ReadByte();
                      _bytesRead = new byte[length];
                      nmc.Read(_bytesRead, 0, length);
                      StreamedData.Add(_bytesRead);
                  }

              }


              var flattenedList = StreamedData.SelectMany(bytes => bytes);
              return ( flattenedList.ToArray());
        }

        public void Dispose()
        {
            this.ioStream.Close();
        }
    }
}
